// Decompiled by Jad v1.5.7g. Copyright 2000 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/SiliconValley/Bridge/8617/jad.html
// Decompiler options: packimports(3) fieldsfirst ansi 
// Source File Name:   Field.java

package lights.dracots;

import java.io.Serializable;
import lights.interfaces.IField;
import lights.interfaces.IValuedField;


public class Field implements IValuedField, Serializable {
	private static final long serialVersionUID = 5812875726641462930L;
	protected Class type;
	protected Serializable value;
	protected Object metaField;
	protected boolean formal;
	
	public static Field MATCH_ALL_FIELD = new MatchAllField();

	public Field() {
		type = null;
		value = null;
		metaField = null;
		formal = true;
	}

	public Object getValue() {
		if (isFormal())
			throw new IllegalArgumentException(
					"Impossible to get the value of a formal field.");
		else
			return value;
	}

	public Class getType() {
		return type;
	}

	public IField setType(Class classObj) {
		if (classObj == null) {
			throw new IllegalArgumentException(
					"Type must refer to a non-null object");
		} else {
			type = classObj;
			formal = true;
			value = null;
			return this;
		}
	}

	public IValuedField setValue(Object value) {
		if (value == null)
			throw new IllegalArgumentException(
					"Value must refer to a non-null object");
		if (!(value instanceof Serializable)) {
			throw new IllegalArgumentException(
					"Values of lights.Field must be Serializable.");
		} else {
			this.value = (Serializable) value;
			type = value.getClass();
			formal = false;
			return this;
		}
	}

	public boolean isFormal() {
		return formal;
	}

	/**
	 * Determines the rule used for pattern matching between fields. <BR>
	 * <code>this.matches(f)</code> returns <code>true</code> if:
	 * <OL>
	 * 
	 * <LI><code>this</code> and <code>f</code> are both actuals, they have
	 * the <I>same type </I>, and they have the <I>same value </I>;
	 * 
	 * <LI>either <code>this</code> or <code>f</code> is a formal, and both
	 * have the same type.
	 * 
	 * </OL>
	 * The above definition assumes that:
	 * 
	 * <OL>
	 * 
	 * <LI>the type of <code>this</code> and <code>f</code> is the same
	 * when their class object (as determined by invoking
	 * <code>getClass()</code> on the field objects) is the same.
	 * 
	 * <LI><code>this</code> and <code>f</code> have the same value when
	 * <code>this.equals(f)</code> returns <code>true</code>.
	 * 
	 * </OL>
	 * 
	 * @return <code>true</code> if the field passed as a parameter matches
	 *         this field, <code>false</code> otherwise.
	 */
	public boolean matches(IField field) {
		if (type == null) {
			throw new IllegalArgumentException(
					"Template fields' type must refer to a non-null object");
		} else if (formal || (field instanceof IValuedField) == false
				|| ((IValuedField) field).isFormal())
			// i.e. either "this" or field is formal
			return this.type.equals(field.getType());
		else
			// i.e. both of them are actual
			return this.type.equals(field.getType())
					&& this.value.equals(((IValuedField) field).getValue());
	}

	public String toString() {
		String result = null;
		if (isFormal())
			result = "[type = " + getType().getName() + "]";
		else
			result = getValue() != null ? getValue().toString() : "null";
		return result;
	}
	
	public boolean equals(Object o) {
		if(this == o)
			return true;
		if(!(o instanceof Field))
			return false;
		
		Field that = (Field)o;
		if(this.isFormal() && that.isFormal())
			return this.getType().equals(that.getType());
		
		if(!this.isFormal() && !that.isFormal())
			return this.getValue().equals(that.getValue());
		return false;
	}
}
